package com.key.win.business.chat.service.impl;

import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.key.win.base.auth.AuthenticationUtil;
import com.key.win.base.page.MybatisPageServiceTemplate;
import com.key.win.base.util.SingleSoldierConstantUtils;
import com.key.win.base.web.PageRequest;
import com.key.win.base.web.PageResult;
import com.key.win.business.chat.dao.ImApplyDao;
import com.key.win.business.chat.eums.ImApplyTypeEnum;
import com.key.win.business.chat.eums.ImMessageTargetEnum;
import com.key.win.business.chat.eums.ImMessageTypeEnum;
import com.key.win.business.chat.model.*;
import com.key.win.business.chat.service.*;
import com.key.win.business.chat.vo.ImApplyVo;
import com.key.win.common.websocket.manager.WebSocketManager;
import com.key.win.system.model.SysUser;
import com.key.win.system.service.SysUserService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;

@Service
public class ImApplyServiceImpl extends ServiceImpl<ImApplyDao, ImApply> implements ImApplyService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private ImApplyDetailService imApplyDetailService;

    @Autowired
    private ImMessageService imMessageService;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private ImGroupService imGroupService;

    @Autowired
    private WebSocketManager webSocketManager;


    @Autowired
    private ImFriendService imFriendService;

    @Autowired
    private ImGroupUserService imGroupUserService;

    public PageResult<ImApply> findApplyByPaged(PageRequest<ImApply> t) {
        MybatisPageServiceTemplate<ImApply, ImApply> query = new MybatisPageServiceTemplate<ImApply, ImApply>(this.baseMapper) {
            @Override
            protected AbstractWrapper constructWrapper(ImApply Apply) {
                LambdaQueryWrapper<ImApply> lambdaQueryWrapper = buildWrapper(Apply);
                return lambdaQueryWrapper;
            }
        };
        return query.doPagingQuery(t);
    }

    private LambdaQueryWrapper<ImApply> buildWrapper(ImApply imApply) {
        if (imApply == null) {
            logger.error("Apply is null!!");
            throw new IllegalArgumentException("查询条件为空！");
        }
        if (StringUtils.isBlank(imApply.getUserId())) {
            logger.error("Apply userId is null!!");
            throw new IllegalArgumentException("发送人为空！");
        }
//        if (imApply.getType() == null) {
//            logger.error("Apply type is null!!");
//            throw new IllegalArgumentException("目标条件为空！");
//        }
        LambdaQueryWrapper<ImApply> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(ImApply::getUserId, imApply.getUserId());
        if (StringUtils.isNotBlank(imApply.getTargetId())) {
            lambdaQueryWrapper.eq(ImApply::getTargetId, imApply.getTargetId());
        }
        if (imApply.getType() != null) {
            lambdaQueryWrapper.eq(ImApply::getType, imApply.getType());
        }
        return lambdaQueryWrapper;
    }

    public List<ImApply> findApply(ImApply imApply) {
        return this.list(this.buildWrapper(imApply));
    }

    /**
     * 申请消息
     * 1、好友申请
     * 2、组申请
     * 先保存申请的ImApply，在保存详情
     * 地详情保存完之后，再次异步保存ImMessage
     * 然后根据用户是否在线，推系统消息
     *
     * @param imApply
     * @return
     */
    public boolean saveOrUpdateApply(ImApply imApply) {
        if (imApply == null) {
            logger.error("Apply is null!!");
            throw new IllegalArgumentException("申请消息为空！");
        }
        if (StringUtils.isBlank(imApply.getUserId())) {
            logger.error("Apply user is null!!");
            throw new IllegalArgumentException("申请人为空！");
        }
        if (imApply.getType() == null) {
            logger.error("Apply type is null!!");
            throw new IllegalArgumentException("目标类型为空！");
        }
        if (StringUtils.isBlank(imApply.getTargetId())) {
            logger.error("Apply trageId is null!!");
            throw new IllegalArgumentException("目标Id为空！");
        }
        List<ImApply> apply = this.findApply(imApply);
        ImApply po = null;
        if (CollectionUtils.isEmpty(apply)) {
            po = imApply;
        } else {
            po = apply.get(0);
        }
        if (this.saveOrUpdate(po)) {
            ImApplyDetail imApplyDetail = new ImApplyDetail();
            imApplyDetail.setApplyId(po.getId());
            imApplyDetail.setUserId(po.getUserId());
            imApplyDetail.setDesc(po.getDesc());
            boolean b = imApplyDetailService.addApplyDetail(imApplyDetail);
            if (b) {
                saveAndSendImMessage(po);
            }
            return b;

        }
        return Boolean.FALSE;
    }

    /**
     * 保存和推送消息
     *
     * @param po
     */
    private void saveAndSendImMessage(ImApply po) {
        String toUserId = "";
        boolean status = false;
        ImGroup imGroup = null;
        if (po.getType() == ImApplyTypeEnum.FRIEND) {
            toUserId = po.getTargetId();
        } else if (po.getType() == ImApplyTypeEnum.GROUP) {
            imGroup = imGroupService.getById(po.getId());
            if (imGroup != null) {
                toUserId = imGroup.getUserId();
            }
        }
        SysUser toUser = AuthenticationUtil.getOnLineUserByUserId(toUserId);
        if (toUser != null) {
            status = true;
        } else {
            toUser = sysUserService.getById(toUserId);
        }
        SysUser fromUser = sysUserService.getById(po.getUserId());
        if (toUser != null) {
            ImMessage imMessage = saveImMessage(po, toUserId, status, imGroup, fromUser);
            if (status) {
                webSocketManager.sendMessageByToken(toUser.getToken(), imMessage);
            }
        }
    }

    /**
     * 保存消息
     *
     * @param po
     * @param toUserId
     * @param status
     * @param imGroup
     * @param fromUser
     * @return
     */
    private ImMessage saveImMessage(ImApply po, String toUserId, boolean status, ImGroup imGroup, SysUser fromUser) {
        ImMessage imMessage = new ImMessage();
        if (po.getResult() == null) {
            if (po.getType() == ImApplyTypeEnum.FRIEND) {
                imMessage.setContent(String.format(SingleSoldierConstantUtils.FRIEND_APPLY_TEMPLATE, fromUser.getUserName()));
            } else if (po.getType() == ImApplyTypeEnum.GROUP) {
                imMessage.setContent(String.format(SingleSoldierConstantUtils.GROUP_APPLY_TEMPLATE, fromUser.getUserName(), imGroup.getName()));
            }
        } else {
            String res = po.getResult() ? "同意" : "拒绝";
            if (po.getType() == ImApplyTypeEnum.FRIEND) {
                imMessage.setContent(String.format(SingleSoldierConstantUtils.FRIEND_APPLY_TEMPLATE_RESULT, fromUser.getUserName(), res));
            } else if (po.getType() == ImApplyTypeEnum.GROUP) {
                imMessage.setContent(String.format(SingleSoldierConstantUtils.GROUP_APPLY_TEMPLATEE_RESULT, fromUser.getUserName(), res, imGroup.getName()));
            }
        }

        imMessage.setFromUserId(fromUser.getId());
        imMessage.setTarget(ImMessageTargetEnum.APPLY);
        imMessage.setTargetId(po.getId());
        imMessage.setType(po.getType() == ImApplyTypeEnum.FRIEND ? ImMessageTypeEnum.SYSTEM_APPLY_FRIEND : ImMessageTypeEnum.SYSTEM_APPLY_GROUP);
        imMessageService.addMessage(imMessage, status, toUserId);
        return imMessage;
    }

    @Override
    public ImApply getImApplyFull(String id) {
        ImApply byId = this.getById(id);
        byId.setImApplyDetails(imApplyDetailService.getImApplyDetailByApplyId(id));
        return byId;
    }

    @Override
    public boolean approve(ImApply apply) {
        if (this.saveOrUpdateApply(apply)) {
            boolean b = false;
            if (apply.getType() == ImApplyTypeEnum.FRIEND) {
                ImFriend imFriend = new ImFriend();
                imFriend.setFriendId(apply.getTargetId());
                imFriend.setUserId(apply.getUserId());
                imFriend.setName(apply.getName());
                imFriend.setGroupId(apply.getGroupId());
                b = imFriendService.addFriend(imFriend);
            } else if (apply.getType() == ImApplyTypeEnum.GROUP) {
                ImGroupUser imGroupUser = new ImGroupUser();
                imGroupUser.setGroupId(apply.getTargetId());
                imGroupUser.setUserId(apply.getUserId());
                imGroupUser.setName(apply.getName());
                b = imGroupUserService.addGroupUser(imGroupUser);
            }
            if (b) {
                saveAndSendImMessage(apply);
            }
            return b;
        }
        return Boolean.FALSE;
    }

    public List<ImApplyVo> findApplyDetail() {
//        LambdaQueryWrapper<ImApplyVo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
//        lambdaQueryWrapper.eq(ImApplyVo::getUserId, AuthenticationUtil.getUserId()).or().eq(ImApplyVo::getToUserId, AuthenticationUtil.getUserId());
        QueryWrapper<ImApplyVo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", AuthenticationUtil.getUserId()).or().eq("to_user_id", AuthenticationUtil.getUserId());
        return this.baseMapper.findImApply(queryWrapper);
    }
}
